package com.pointi.emoGatewayM;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ConcurrentLinkedQueue;

import com.pointi.emoConverterM.ThreadController;
import com.pointi.emoConverterM.ThreadScheduler;
import com.pointi.emoTools.DefineParam;

public class emoGateway
{
	public static void main(String[] ar) throws Exception
	{
		//____________________________________________________________________________________________________
		// CONFIGURATION

		String str_conffile = "emoGatewayM.conf";
		ConfigurationData conf_data = new ConfigurationData() ;
		conf_data.InitializeData() ;
		try {
			conf_data = conf_data.ReadConfXML(str_conffile) ;
			conf_data.WriteLogConfigurationData(conf_data) ;
		} catch (Exception e) {
			System.out.println("[GW] Can't Read XML File!! - "+str_conffile) ;
			e.printStackTrace() ;
		}

		//____________________________________________________________________________________________________
		// JDBC

		JDBC jdbc = new JDBC() ;
		jdbc.SetDatabaseParam(conf_data) ;
		DefineParam define = new DefineParam() ;
		int nRet = define.DB_CONNECT_FAIL ;
		while (true) {
			nRet = jdbc.fnConnectDB() ;
			if (nRet == define.DB_CONNECT_SUCCESS) break ;
			System.out.println("[GW] Record DB Connect - "+nRet) ;
			Thread.sleep(1000) ;
		}
		jdbc.fnPrepareDatabase() ;
		
		//____________________________________________________________________________________________________
		// SERVER SOCKET 

		ServerSocket serverSocket = null ;
		Socket socket = null ;
		int mServerPort = Integer.valueOf(conf_data.s_gateway_port) ;
		try {
			serverSocket = new ServerSocket(mServerPort) ;
			System.out.println("[GW] Server Waiting for Client on Port : " + serverSocket.getLocalPort()) ;
		} catch (IOException e) { e.printStackTrace() ; }

		//____________________________________________________________________________________________________
		// THREAD

		ConcurrentLinkedQueue<ThreadController> _Controller = new ConcurrentLinkedQueue<ThreadController>() ;
		ConcurrentLinkedQueue<ThreadScheduler> _Scheduler = new ConcurrentLinkedQueue<ThreadScheduler>() ;
		ConcurrentLinkedQueue<ThreadReceiver> _Receiver = new ConcurrentLinkedQueue<ThreadReceiver>() ;
		AliveInfo mAliveInfo = new AliveInfo() ;

		int mThreadLimit = Integer.valueOf(conf_data.s_thread_limit) ;
		int mThreadCount = 0 ;
		boolean loopHandler = true ;
		while (loopHandler)
		{
			//____________________________________________________________________________________________________
			// FILE RECEIVER

			if (_Receiver.isEmpty()) _Receiver = new ConcurrentLinkedQueue<ThreadReceiver>() ;
			mThreadCount = _Receiver.size() ;
			if (mThreadCount < mThreadLimit) {
				try {
					socket = serverSocket.accept() ;
					new ThreadReceiver(_Receiver).start(socket, conf_data, jdbc) ;
					System.out.println("[GW] New Client asked for a connection ! " + socket.getInetAddress()) ;
				} catch (Exception e) { e.printStackTrace() ; }
			}
			
			//____________________________________________________________________________________________________
			// FILE CONVERTER (CONTROLLER > CONVERTER)

			System.out.println("[GW][CVT] Checking.. Received File") ;
			if (_Controller.isEmpty()) _Controller = new ConcurrentLinkedQueue<ThreadController>() ;
			mThreadCount = _Controller.size() ;
			if (mThreadCount < 1) {
				System.out.println("[GW][CVT] Start Converter Controller") ;
				new ThreadController(_Controller).start(jdbc, conf_data) ;
			}

			//____________________________________________________________________________________________________
			// WORK SCHEDULER

			if (_Scheduler.isEmpty()) _Scheduler = new ConcurrentLinkedQueue<ThreadScheduler>() ;
			mThreadCount = _Scheduler.size() ;
			if (mThreadCount < 1) {
				System.out.println("[GW][WKS] Start Work Scheduler") ;
				new ThreadScheduler(_Scheduler).start(jdbc, mAliveInfo, Integer.valueOf(conf_data.s_check_interval)) ;
			}
			Thread.sleep(500) ;
		}
		System.out.println("[GW] END") ;
	}
}